package top.codechap.extension;

import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import top.codechap.extension.model.Black;

/**
 * @author CodeChap
 * @date 2021-06-24 9:45
 * @description ExtensionConfig
 *
 * 扩展原理:
 * BeanPostProcessor: bean后置处理器, bean创建对象初始化前后进行拦截工作
 *
 * 1. BeanFactoryPostProcessor: beanFactory的后置处理器
 *      调用时机: 在BeanFactory 标准初始化 之后调用; 所有的bean 定义已经被保存加载到beanFactory中, 但是bean的实例还没有创建
 *      调用流程:
 *      1) ioc容器创建对象
 *      2) 容器调用refresh() 方法
 *      3) invokeBeanFactoryPostProcessors(beanFactory): 执行BeanFactoryPostProcessors
 *          如何找到所有的BeanFactoryPostProcessors 并执行他们的方法?
 *              (1) 直接在BeanFactory中找到所有类型为BeanFactoryPostProcessor 的组件,并执行他们的方法
 *              (2) 在初始化创建其他组件前面执行
 *
 * 2. BeanDefinitionRegistryPostProcessor接口:
 *    BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor
 *      这个子接口新增了方法: postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
 *      调用时机: 在所有bean 定义信息将要被加载, bean实例还未创建时
 *      BeanDefinitionRegistryPostProcessor 是优先于BeanFactoryPostProcessor 执行,可以利用BeanDefinitionRegistryPostProcessor 给容器中再额外添加一些组件
 *      调用流程:
 *          1) ioc容器创建对象
 *          2) 容器调用refresh() -> invokeBeanFactoryPostProcessors(beanFactory)
 *          3) 先从容器中获取到所有的BeanDefinitionRegistryPostProcessor 组件[即,currentRegistryProcessors], 执行invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors)方法,依次触发所有的beanDefinitionRegistryPostProcessors 方法,
 *              然后再执行invokeBeanFactoryPostProcessors()方法, 触发beanFactoryPostProcessors 方法,并执行里面的 postProcessBeanFactory(beanFactory)方法,从而执行BeanFactoryPostProcessors
 *          4) 再后来,从容器中找到BeanFactoryPostProcessor 组件,然后依次触发postProcessBeanFactory(beanFactory)方法,从而执行BeanFactoryPostProcessors
 *
 * 3. ApplicationListener: 监听容器中发布的事件, 完成事件驱动模型的开发
 *    public interface ApplicationListener<E extends ApplicationEvent>
 *        监听ApplicationEvent 及其下面的子事件;
 *
 *        基于事件开发的步骤:
 *              1) 写一个监听器,监听某个事件,这个事件必须是ApplicationEvent 及其下面的子事件;
 *              2) 把监听器加入到容器中;
 *              3) 只要容器中有相关事件的发布, 我们就能监听到这个事件;
 *                  ContextRefreshedEvent: 容器刷新完成(所有bean都完全创建)时,会发布这个事件;
 *                  ContextClosedEvent: 关闭容器会发布这个事件
 *              4) 发布一个事件:
 */

@Configuration
@ComponentScan("top.codechap.extension")
public class ExtensionConfig {
//    BeanFactoryPostProcessor
    @Bean
    public Black black() {
        return new Black();
    }
}
